From 933c704332789fa9c3955e7784dfb0ba40803679 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 25 Sep 2008 10:26:08 +0100 Subject: [PATCH] x86: Fix guest_physmap_add_entry checks guest_physmap_add_entry() checks to see if the given mfn and gpfn range in the p2m and m2p tables is already mapped before overwriting the maps, and attempts to do something reasonable so that we don't have any "dangling" pointers. Unfortunately, these checks got broken when the page_order argument was added. Each individual p2m and m2p entry needs to be checked, not just the first page in a page order. Signed-off-by: George Dunlap --- xen/arch/x86/mm/p2m.c | 51 +++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index bf97d45c00..15d5297371 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -953,38 +953,47 @@ guest_physmap_add_entry(struct domain *d, unsigned long gfn, P2M_DEBUG("adding gfn=%#lx mfn=%#lx\n", gfn, mfn); - omfn = gfn_to_mfn(d, gfn, &ot); - if ( p2m_is_ram(ot) ) + /* First, remove m->p mappings for existing p->m mappings */ + for ( i = 0; i < (1UL << page_order); i++ ) { - ASSERT(mfn_valid(omfn)); - for ( i = 0; i < (1UL << page_order); i++ ) + omfn = gfn_to_mfn(d, gfn, &ot); + if ( p2m_is_ram(ot) ) + { + ASSERT(mfn_valid(omfn)); set_gpfn_from_mfn(mfn_x(omfn)+i, INVALID_M2P_ENTRY); + } } - ogfn = mfn_to_gfn(d, _mfn(mfn)); - if ( + /* Then, look for m->p mappings for this range and deal with them */ + for ( i = 0; i < (1UL << page_order); i++ ) + { + ogfn = mfn_to_gfn(d, _mfn(mfn)); + if ( #ifdef __x86_64__ - (ogfn != 0x5555555555555555L) + (ogfn != 0x5555555555555555L) #else - (ogfn != 0x55555555L) + (ogfn != 0x55555555L) #endif - && (ogfn != INVALID_M2P_ENTRY) - && (ogfn != gfn) ) - { - /* This machine frame is already mapped at another physical address */ - P2M_DEBUG("aliased! mfn=%#lx, old gfn=%#lx, new gfn=%#lx\n", - mfn, ogfn, gfn); - omfn = gfn_to_mfn(d, ogfn, &ot); - if ( p2m_is_ram(ot) ) + && (ogfn != INVALID_M2P_ENTRY) + && (ogfn != gfn) ) { - ASSERT(mfn_valid(omfn)); - P2M_DEBUG("old gfn=%#lx -> mfn %#lx\n", - ogfn , mfn_x(omfn)); - if ( mfn_x(omfn) == mfn ) - p2m_remove_page(d, ogfn, mfn, page_order); + /* This machine frame is already mapped at another physical + * address */ + P2M_DEBUG("aliased! mfn=%#lx, old gfn=%#lx, new gfn=%#lx\n", + mfn, ogfn, gfn); + omfn = gfn_to_mfn(d, ogfn, &ot); + if ( p2m_is_ram(ot) ) + { + ASSERT(mfn_valid(omfn)); + P2M_DEBUG("old gfn=%#lx -> mfn %#lx\n", + ogfn , mfn_x(omfn)); + if ( mfn_x(omfn) == mfn ) + p2m_remove_page(d, ogfn, mfn, 0); + } } } + /* Now, actually do the two-way mapping */ if ( mfn_valid(_mfn(mfn)) ) { if ( !set_p2m_entry(d, gfn, _mfn(mfn), page_order, t) ) -- 2.30.2